﻿'Copyright (C) 2010  Thomas Huebner
'
'This program is free software
'
'you can redistribute it and/or modify it under the terms 
'of the GNU General Public License as published by the 
'Free Software Foundation either version 2 of the License, 
'or (at your option) any later version.
'
'This program is distributed in the hope that it will be 
'useful, but WITHOUT ANY WARRANTY without even the implied 
'warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
'See the GNU General Public License for more details.
'
'You should have received a copy of the GNU General Public License 
'along with this program; if not, write to the 
'Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
'Boston, MA 02111-1307, USA. 


Imports System.IO

Public Class LF_Parameters
    Inherits Dictionary(Of String, String)

    ''' <summary>
    ''' Enumerator to fork between different API Entry points
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum RequestType
        Area
        Initiative
        Suggestion
    End Enum

    ''' <summary>
    ''' Defines the actual parameter orientation
    ''' </summary>
    ''' <remarks></remarks>
    Private _Request As RequestType

    ''' <summary>
    ''' BaseURL for Liquid Feedback
    ''' </summary>
    ''' <remarks></remarks>
    Private _BaseURL As String

    ''' <summary>
    ''' Personal Token for Liquid Feedback
    ''' </summary>
    ''' <remarks></remarks>
    Private _Token As String

    ''' <summary>
    ''' Bytemask for Area avail API parameters
    ''' </summary>
    ''' <remarks>0000 0100</remarks>
    Private Const VALID_AREA As Byte = &H4

    ''' <summary>
    ''' Bytemask for Initiative avail API parameters
    ''' </summary>
    ''' <remarks>0000 0010</remarks>
    Private Const VALID_INITIATIVE As Byte = &H2

    ''' <summary>
    ''' Bytemask for Suggestion avail API parameters
    ''' </summary>
    ''' <remarks>0000 0001</remarks>
    Private Const VALID_SUGGESTION As Byte = &H1

    ''' <summary>
    ''' Array of all available parameters
    ''' </summary>
    ''' <remarks>availabability is managed over same position Bitmask of ValidParameters.
    ''' If you add a new parameter here you must add the validity byte with same index in
    ''' Array ValidParameters</remarks>
    Private AllParameters() As String = {"api_engine", _
                                         "id", _
                                         "min_id", _
                                         "max_id", _
                                         "area_id", _
                                         "issue_id", _
                                         "policy_id", _
                                         "state", _
                                         "agreed", _
                                         "limit", _
                                         "order", _
                                         "render_draft", _
                                         "initiative_id"}

    ''' <summary>
    ''' Validation Array
    ''' </summary>
    ''' <remarks>Example 0x07 = 0000 0111 = allowed for all API entry points</remarks>
    Private ValidParameters() As Byte = {&H7, _
                                         &H7, _
                                         &H7, _
                                         &H7, _
                                         &H2, _
                                         &H2, _
                                         &H2, _
                                         &H2, _
                                         &H2, _
                                         &H7, _
                                         &H7, _
                                         &H2, _
                                         &H1}


    ''' <summary>
    ''' Overloaded contructor to set BaseURL and Token while instancing
    ''' </summary>
    ''' <param name="Request"></param>
    ''' <param name="BaseURL"></param>
    ''' <param name="Token"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Request As RequestType, ByVal BaseURL As String, ByVal Token As String)
        Me._Request = Request
        Me._BaseURL = BaseURL
        Me._Token = Token
    End Sub


    ''' <summary>
    ''' Returns all parameters from inherited list as URL parameter string
    ''' </summary>
    ''' <returns>String</returns>
    ''' <remarks>Returns an empty string if no parameter is found</remarks>
    Private Function GetParameterString() As String

        If Me.Count > 0 Then
            Using sw As New StringWriter

                For Each kp As KeyValuePair(Of String, String) In Me
                    sw.Write(String.Format("&{0}={1}", kp.Key, kp.Value))
                Next

                Return sw.ToString

            End Using
        Else
            Return String.Empty
        End If

    End Function


    ''' <summary>
    ''' Returns a complete URL to call the Liquid Feedback API
    ''' </summary>
    ''' <returns>String</returns>
    ''' <remarks>Overloaded - if using this function you must set 
    ''' BaseURL and Token with constructor</remarks>
    Public Function GetURL() As String

        If String.IsNullOrEmpty(Me._BaseURL) Then
            Dim ex As New Exception("BaseURL not set")
            Throw ex
        End If

        If String.IsNullOrEmpty(Me._Token) Then
            Dim ex As New Exception("Token not set")
            Throw ex
        End If

        Return GetURL(Me._BaseURL, Me._Token)

    End Function


    ''' <summary>
    ''' Returns a complete URL to call the Liquid Feedback API
    ''' </summary>
    ''' <param name="BaseURL"></param>
    ''' <param name="Token"></param>
    ''' <returns></returns>
    ''' <remarks>Overloaded - if using this function you must not set 
    ''' the BaseURL and Token before</remarks>
    Public Function GetURL(ByVal BaseURL As String, ByVal Token As String) As String

        Using sw As New StringWriter

            'write base URL first
            sw.Write(BaseURL)

            'if not base UL ends with slash -> add it
            If Not BaseURL.EndsWith("/") Then
                sw.Write("/")
            End If

            'add API entry point
            Select Case Me._Request

                Case RequestType.Area
                    sw.Write("area.html")

                Case RequestType.Initiative
                    sw.Write("initiative.html")

                Case RequestType.Suggestion
                    sw.Write("suggestion.html")

            End Select

            'add token as first API Parameter
            sw.Write(String.Format("?key={0}", Token))

            'set API Engine to XML as needed for deserializer
            sw.Write("&api_engine=xml")

            'add specific parameters
            sw.Write(GetParameterString)

            Return sw.ToString

        End Using

    End Function


    ''' <summary>
    ''' Add a Liquid Feedback API parameter.
    ''' </summary>
    ''' <param name="APIParameter"></param>
    ''' <param name="Value"></param>
    ''' <remarks>The parameter is checked for validity related to API entry point</remarks>
    Public Sub AddParameter(ByVal APIParameter As String, ByVal Value As String)

        'Errorcode
        Dim rc As Integer = -1

        If Not Me.ContainsKey(APIParameter) Then

            'Find the parameter in array of all parameters
            Dim idx As Integer = Array.IndexOf(AllParameters, APIParameter)

            'Parameter found
            If idx > (-1) Then

                'Check validity depending on bitmask
                Select Case Me._Request

                    Case RequestType.Area
                        If (ValidParameters(idx) And VALID_AREA) = VALID_AREA Then
                            Me.Add(APIParameter, Value)
                        Else
                            rc = 2
                        End If

                    Case RequestType.Initiative
                        If (ValidParameters(idx) And VALID_INITIATIVE) = VALID_INITIATIVE Then
                            Me.Add(APIParameter, Value)
                        Else
                            rc = 3
                        End If

                    Case RequestType.Suggestion
                        If (ValidParameters(idx) And VALID_SUGGESTION) = VALID_SUGGESTION Then
                            Me.Add(APIParameter, Value)
                        Else
                            rc = 4
                        End If

                End Select
            Else
                rc = 1
            End If

        Else
            rc = 0
        End If

        'Build errormessage and throw exception
        If rc > -1 Then

            Dim src() As String = {"Parameter already exist", _
                                   "Not a LF Parameter", _
                                   "Not Valid for Area", _
                                   "Not Valid for Initiative", _
                                   "Not Valid for suggestion"}

            Dim ex As New Exception(src(rc))
            Throw ex

        End If

    End Sub

End Class
